home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 418_03 / outfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-02  |  49.9 KB  |  1,882 lines

  1. /* outfile.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, February 1994
  4.  * Version 2.3
  5.  */
  6. #define OUTFILE
  7. #include "rasmol.h"
  8.  
  9. #ifdef IBMPC
  10. #include <windows.h>
  11. #include <malloc.h>
  12. #endif
  13. #ifndef sun386
  14. #include <stdlib.h>
  15. #endif
  16.  
  17. #include <stdio.h>
  18. #include <ctype.h>
  19. #include <math.h>
  20.  
  21. #include "outfile.h"
  22. #include "molecule.h"
  23. #include "command.h"
  24. #include "transfor.h"
  25. #include "render.h"
  26. #include "graphics.h"
  27. #include "pixutils.h"
  28.  
  29.  
  30. #ifdef EIGHTBIT
  31. #define RComp(x)   (RLut[LutInv[x]])
  32. #define GComp(x)   (GLut[LutInv[x]])
  33. #define BComp(x)   (BLut[LutInv[x]])
  34. #else
  35. #define RComp(x)   (((x)>>16)&0xff)
  36. #define GComp(x)   (((x)>>8)&0xff)
  37. #define BComp(x)   ((x)&0xff)
  38. #endif
  39.  
  40.  
  41. /* Sun rasterfile.h macro defns */
  42. #define RAS_MAGIC       0x59a66a95
  43. #define RAS_RLE         0x80
  44. #define RT_STANDARD     1
  45. #define RT_BYTE_ENCODED 2
  46. #define RMT_NONE        0
  47. #define RMT_EQUAL_RGB   1
  48.  
  49. /* Standard A4 size page: 8.267x11.811 inches */
  50. /* U.S. Normal size page: 8.500x11.000 inches */
  51. #define PAGEHIGH  (11.811*72.0)
  52. #define PAGEWIDE  (8.267*72.0)
  53. #define BORDER    0.90
  54.  
  55. /* Compression Ratio   0<x<127 */
  56. #define EPSFCompRatio  32
  57.  
  58. #define Round(x)  ((int)(x))
  59. #define Rad2Deg   (180.0/PI)
  60. #define Deg2Rad   (PI/180.0)
  61.  
  62.  
  63. #define PSLine    0x00
  64. #define PSStick   0x01
  65. #define PSSphere  0x02
  66.  
  67. typedef void __far* PSItemPtr;
  68.  
  69.  
  70. #ifdef IBMPC
  71. static short __far *ABranch;
  72. static short __far *DBranch;
  73. static short __far *Hash;
  74. static Byte __far *Node;
  75. #else
  76. static short ABranch[4096];
  77. static short DBranch[4096];
  78. static short Hash[256];
  79. static Byte Node[4096];
  80. #endif
  81.  
  82.  
  83. typedef struct {
  84.     Byte len;
  85.     Byte ch;
  86.         } BMPPacket;
  87.         
  88.  
  89. static BMPPacket BMPBuffer[10];
  90. static int BMPCount,BMPTotal;        
  91. static int BMPPad;
  92.  
  93. static int GIFClrCode; 
  94. static int GIFEOFCode;
  95.  
  96. static Card RLEFileSize;
  97. static int RLEEncode;
  98. static int RLEOutput;
  99. static int RLELength;
  100. static int RLEPixel;
  101. static int RLEChar;
  102.  
  103.  
  104. static Byte Buffer[256];
  105. static Byte LutInv[256];
  106. static int LineLength;
  107. static FILE *OutFile;
  108. static Card BitBuffer;
  109. static int BitBufLen;
  110. static int PacketLen;
  111. static int CodeSize;
  112.  
  113. static Real LineWidth;
  114. static int VectSolid;
  115. static int VectCol;
  116.  
  117. /* Macros for commonly used loops */
  118. #define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
  119.                      for(group=chain->glist;group;group=group->gnext)    \
  120.                      for(aptr=group->alist;aptr;aptr=aptr->anext)
  121. #define ForEachBond  for(bptr=Database->blist;bptr;bptr=bptr->bnext)
  122. #define ForEachBack  for(chain=Database->clist;chain;chain=chain->cnext) \
  123.                      for(bptr=chain->blist;bptr;bptr=bptr->bnext)
  124.  
  125.  
  126.  
  127. static void FatalOutputError( ptr )
  128.     char *ptr;
  129. {
  130.     if( CommandActive ) WriteChar('\n');
  131.     WriteString("Output Error: Unable to create file `");
  132.     WriteString( ptr );  WriteString("'!\n");
  133.     CommandActive = False;
  134. }
  135.  
  136.  
  137.  
  138. static void WritePPMWord( i )
  139.     int i;
  140. {
  141.     if( i>99 )
  142.     {   fputc((i/100)+'0',OutFile); i %= 100;
  143.         fputc((i/10) +'0',OutFile); i %= 10;
  144.     } else if( i>9 )
  145.     {   fputc((i/10)+'0',OutFile);  i %= 10;
  146.     }
  147.     putc(i+'0',OutFile);
  148. }
  149.  
  150.  
  151. int WritePPMFile( name, raw )
  152.     char *name;  int raw;
  153. {
  154.     register Pixel __huge *ptr;
  155.     register int i, c;
  156.     register int x,y;
  157.  
  158. #ifdef IBMPC
  159.     OutFile = fopen(name, (raw?"wb":"w") );
  160. #else
  161.     OutFile = fopen(name,"w");
  162. #endif
  163.  
  164.     if( !OutFile ) 
  165.     {   FatalOutputError(name);
  166.         return( False );
  167.     }
  168.     fputc('P',OutFile); fputc((raw?'6':'3'),OutFile);
  169.     fprintf(OutFile," %d %d 255\n",XRange,YRange);
  170.  
  171. #ifdef EIGHTBIT
  172.     for( i=0; i<256; i++ )
  173.         if( ULut[i] )
  174.             LutInv[Lut[i]] = i;
  175. #endif
  176.  
  177. #ifdef IBMPC
  178.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  179. #endif
  180.  
  181. #ifndef INVERT
  182.     ptr = FBuffer;
  183. #endif
  184.  
  185.     c = 0;
  186.  
  187.     if( !raw )
  188.     {   c = 0;
  189.         for( y=YRange-1; y>=0; y-- )
  190.         {
  191. #ifdef INVERT
  192.             ptr = FBuffer + (Long)y*XRange;
  193. #endif
  194.             for( x=0; x<XRange; x++ )
  195.             {   i = *ptr++; c++;
  196.                 WritePPMWord((int)RComp(i));  fputc(' ',OutFile);
  197.                 WritePPMWord((int)GComp(i));  fputc(' ',OutFile);
  198.                 WritePPMWord((int)BComp(i));  
  199.                 if( c==5 )
  200.                 { c=0; fputc('\n',OutFile);
  201.                 } else fputc(' ',OutFile);
  202.             }
  203.         }
  204.     } else
  205.         for( y=YRange-1; y>=0; y-- )
  206.         {
  207. #ifdef INVERT
  208.             ptr = FBuffer + (Long)y*XRange;
  209. #endif
  210.             for( x=0; x<XRange; x++ )
  211.             {   i = *ptr++;
  212.                 fputc((int)RComp(i),OutFile);
  213.                 fputc((int)GComp(i),OutFile);
  214.                 fputc((int)BComp(i),OutFile);
  215.             }
  216.         }
  217.  
  218.     fclose(OutFile);
  219. #ifdef IBMPC
  220.     GlobalUnlock(FBufHandle); 
  221. #endif
  222.     return( True );
  223. }
  224.  
  225.  
  226.  
  227. #ifdef EIGHTBIT
  228. static int CompactColourMap()
  229. {
  230.     register Pixel __huge *ptr;
  231.     register Long pos, count;
  232.     register int i, cols;
  233.  
  234.     for( i=0; i<256; i++ )
  235.     {   if( ULut[i] )
  236.             LutInv[Lut[i]] = i;
  237.         Buffer[i] = 0;
  238.         Node[i] = 5;
  239.     }
  240.  
  241. #ifdef IBMPC
  242.     ptr = (Pixel __huge*)GlobalLock(FBufHandle);    
  243. #else
  244.     ptr = FBuffer;
  245. #endif
  246.  
  247.     cols = 0;
  248.     count = (Long)XRange*YRange;
  249.     for( pos=0; pos<count; pos++ )
  250.     {   i = LutInv[*ptr++];
  251.         if( !Buffer[i] ) 
  252.         {   Node[cols++] = i;
  253.             Buffer[i] = cols;
  254.         }
  255.     }
  256.  
  257.     for( i=0; i<256; i++ )
  258.         LutInv[i] = Buffer[LutInv[i]]-1;
  259. #ifdef IBMPC
  260.     GlobalUnlock(FBufHandle);
  261. #endif
  262.     return( cols );
  263. }
  264. #endif
  265.  
  266.  
  267.  
  268. static void WriteGIFCode( code )
  269.     int code;
  270. {
  271.     register int max;
  272.  
  273.     max = (code==GIFEOFCode)? 0 : 7;
  274.     BitBuffer |= ((Card)code<<BitBufLen);
  275.     BitBufLen += CodeSize;
  276.  
  277.     while( BitBufLen > max )
  278.     {    
  279. #ifdef IBMPC
  280.          Buffer[PacketLen++]=(Byte)(BitBuffer&0xff);
  281. #else
  282.          Buffer[PacketLen++]=BitBuffer;
  283. #endif
  284.          BitBuffer >>= 8;
  285.          BitBufLen -= 8;
  286.  
  287.         if( PacketLen==255 )
  288.         {   fputc(0xff,OutFile);
  289.             fwrite((char*)Buffer,1,255,OutFile);
  290.             PacketLen = 0;
  291.         }
  292.     }
  293. }
  294.  
  295. int WriteGIFFile( name )
  296.     char *name;
  297. {
  298.     register int i,j,cols;
  299.     register int pref,next,last;
  300.     register int isize, ilast;
  301.     register Pixel __huge *ptr;
  302.     register short __far *prev;
  303.     register int x,y,init;
  304.  
  305. #ifdef EIGHTBIT
  306.     cols = CompactColourMap();
  307.     if( cols<2 ) return( False );
  308.  
  309.     for( isize=0; isize<8; isize++ )
  310.         if( (1<<isize)>=cols ) break;
  311.     cols = 1<<isize;
  312.  
  313. #ifdef IBMPC
  314.     OutFile = fopen(name,"wb");
  315. #else
  316.     OutFile = fopen(name,"w");
  317. #endif
  318.     if( !OutFile ) 
  319.     {    FatalOutputError(name);
  320.          return( False );
  321.     }
  322.     fwrite("GIF87a",1,6,OutFile);
  323.     fputc(XRange&0xff,OutFile);  fputc((XRange>>8)&0xff,OutFile);
  324.     fputc(YRange&0xff,OutFile);  fputc((YRange>>8)&0xff,OutFile);
  325.     fputc(0xf0|(isize-1),OutFile); 
  326.     fputc(0x00,OutFile); 
  327.     fputc(0x00,OutFile);
  328.  
  329.     for( j=0; j<cols; j++ )
  330.     {   i = Node[j];
  331.         fputc((int)RLut[i],OutFile);
  332.         fputc((int)GLut[i],OutFile);
  333.         fputc((int)BLut[i],OutFile);
  334.     }
  335.  
  336.     fputc(',',OutFile);
  337.     fputc(0x00,OutFile);  fputc(0x00,OutFile);
  338.     fputc(0x00,OutFile);  fputc(0x00,OutFile);
  339.     fputc(XRange&0xff,OutFile);  fputc((XRange>>8)&0xff,OutFile);
  340.     fputc(YRange&0xff,OutFile);  fputc((YRange>>8)&0xff,OutFile);
  341.     fputc(0x00,OutFile);  fputc(isize,OutFile);
  342.  
  343.     PacketLen=0;
  344.     BitBuffer=0;
  345.     BitBufLen=0;
  346.  
  347.     GIFClrCode = (1<<isize);
  348.     GIFEOFCode = GIFClrCode+1;
  349.     ilast = (GIFClrCode<<1)-GIFEOFCode;
  350.     isize++;
  351.  
  352.     CodeSize = isize;
  353.     last = ilast;
  354.     next = 1;  
  355.    
  356.     WriteGIFCode(GIFClrCode);
  357.     for( i=0; i<cols; i++ )
  358.         Hash[i]=0;
  359.  
  360. #ifdef IBMPC
  361.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);    
  362. #endif
  363.  
  364. #ifndef INVERT
  365.     ptr = FBuffer;
  366. #endif
  367.  
  368.     /* Avoid Warnings! */
  369.     prev = (short __far*)0; 
  370.     pref = 0;
  371.  
  372.     init = False;
  373.     for( y=YRange-1; y>=0; y-- )
  374.     {   
  375. #ifdef INVERT
  376.         ptr = FBuffer + (Long)y*XRange;
  377. #endif
  378.         for( x=0; x<XRange; x++ )
  379.         {   if( !init )
  380.             {   pref = LutInv[*ptr++];
  381.                 prev = Hash+pref;
  382.                 init = True;
  383.                 continue;
  384.             }
  385.  
  386.             i = LutInv[*ptr++];
  387.  
  388.             while( *prev && (Node[*prev] != (Byte)i) )
  389.                 prev = ABranch+*prev;
  390.  
  391.             if( *prev )
  392.             {   pref = *prev+GIFEOFCode;
  393.                 prev = DBranch+*prev;
  394.             } else
  395.             {   WriteGIFCode(pref);
  396.                 if( next==last )
  397.                 {   if( CodeSize==12 )
  398.                     {   WriteGIFCode(GIFClrCode);
  399.                         pref = i;  prev = Hash+i;
  400.                         for( i=0; i<cols; i++ )
  401.                             Hash[i] = 0;
  402.                         CodeSize = isize;
  403.                         last = ilast;
  404.                         next = 1; 
  405.                         continue;
  406.                     }
  407.                     last = (last<<1)+GIFEOFCode;
  408.                     CodeSize++;
  409.                 }
  410.                 *prev = next;
  411.                 ABranch[next] = 0;
  412.                 DBranch[next] = 0;
  413.                 Node[next] = i;
  414.                 prev = Hash+i;
  415.                 pref = i;
  416.                 next++;
  417.             }
  418.         }
  419.     }
  420.  
  421.  
  422.     WriteGIFCode(pref);
  423.     WriteGIFCode(GIFEOFCode);
  424.     if( PacketLen )
  425.     {   fputc(PacketLen,OutFile);
  426.         fwrite((char*)Buffer,1,PacketLen,OutFile);
  427.     }
  428.  
  429.     fputc(0x00,OutFile);
  430.     fputc(';',OutFile);
  431.     fclose(OutFile);
  432.  
  433. #ifdef IBMPC
  434.     GlobalUnlock(FBufHandle);
  435. #endif
  436.     return( True );
  437. #else
  438.     if( CommandActive ) WriteChar('\n');
  439.     WriteString("Output Error: 24 bit GIF files unsupported!\n");
  440.     CommandActive = False;
  441.     return( False );
  442. #endif
  443. }
  444.  
  445. /* Function Prototype */
  446. #if defined(__STDC__) || defined(IBMPC)
  447. static void WriteRastInt( Card );
  448. #endif
  449.  
  450. static void WriteRastInt( val )
  451.     Card val;
  452. {
  453.     fputc((int)((val>>24)&0xff),OutFile);
  454.     fputc((int)((val>>16)&0xff),OutFile);
  455.     fputc((int)((val>>8) &0xff),OutFile);
  456.     fputc((int)(val&0xff),OutFile);
  457. }
  458.  
  459.  
  460. static void FlushRastRLE()
  461. {
  462.     if( RLEChar==RAS_RLE )
  463.     {   if( RLEOutput )
  464.         {   fputc(RAS_RLE,OutFile);
  465.             fputc(RLELength-1,OutFile);
  466.             if( RLELength!=1 )
  467.                 fputc(RAS_RLE,OutFile);
  468.         } else RLEFileSize += (RLELength>1)? 3 : 2;
  469.     } else
  470.         if( RLEOutput )
  471.         {   if( RLELength>2 )
  472.             {   fputc(RAS_RLE,OutFile);
  473.                 fputc(RLELength-1,OutFile);
  474.             } else if( RLELength==2 )
  475.                 fputc(RLEChar,OutFile);
  476.             fputc(RLEChar,OutFile);
  477.         } else RLEFileSize += MinFun(RLELength,3);
  478. }
  479.  
  480.  
  481. static void WriteRastRLECode( val )
  482.     int val;
  483. {
  484.     if( RLEEncode )
  485.     {   if( !RLELength )
  486.         {   RLELength = 1;
  487.             RLEChar = val;
  488.         } else
  489.             if( (RLEChar!=val) || (RLELength==256) )
  490.             {   FlushRastRLE();
  491.                 RLELength = 1;
  492.                 RLEChar = val;
  493.             } else
  494.                 RLELength++;
  495.     } else
  496.         fputc(val,OutFile);
  497. }
  498.  
  499. static void WriteRastRLEPad()
  500. {
  501.     if( RLEEncode )
  502.     {   if( !RLELength || (RLELength==256) )
  503.         {   WriteRastRLECode(0x00);
  504.         } else RLELength++;
  505.     } else fputc(0x00,OutFile);
  506. }
  507.  
  508.  
  509. static void WriteRastData( output )
  510.     int output;
  511. {
  512.     register Pixel __huge *ptr;
  513.     register int x,y,pad;
  514. #ifndef EIGHTBIT
  515.     register int i;
  516. #endif
  517.  
  518. #ifdef IBMPC
  519.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  520. #endif
  521.  
  522. #ifndef INVERT
  523.     ptr = FBuffer;
  524. #endif
  525.  
  526.     pad = XRange%2;
  527.  
  528.     RLEOutput = output;
  529.     RLEFileSize = 0;
  530.     RLELength = 0;
  531.  
  532.     for( y=YRange-1; y>=0; y-- )
  533.     {   
  534. #ifdef INVERT
  535.         ptr = FBuffer + (Long)y*XRange;
  536. #endif
  537.         for( x=0; x<XRange; x++ )
  538. #ifndef EIGHTBIT
  539.         {   i = *ptr++;
  540.             WriteRastRLECode((int)BComp(i));
  541.             WriteRastRLECode((int)GComp(i));
  542.             WriteRastRLECode((int)RComp(i));
  543.         }
  544. #else
  545.             WriteRastRLECode((int)LutInv[*ptr++]);
  546. #endif
  547.         if( pad ) WriteRastRLEPad();
  548.     }
  549.  
  550.     if( RLEEncode && RLELength )
  551.         FlushRastRLE();
  552. #ifdef IBMPC
  553.     GlobalUnlock(FBufHandle);
  554. #endif
  555. }
  556.  
  557.  
  558.  
  559. int WriteRastFile( name, encode )
  560.     char *name;
  561.     int encode;
  562. {
  563.     register int i,size,cols;
  564.  
  565. #ifdef IBMPC
  566.     OutFile = fopen(name,"wb");
  567. #else
  568.     OutFile = fopen(name,"w");
  569. #endif
  570.  
  571.     if( !OutFile )
  572.     {   FatalOutputError(name);
  573.         return(False);
  574.     }
  575.     WriteRastInt( RAS_MAGIC );
  576.     WriteRastInt(XRange);  
  577.     WriteRastInt(YRange);
  578.     RLEEncode = encode;
  579.  
  580.  
  581. #ifdef EIGHTBIT
  582.     WriteRastInt(8);
  583.  
  584.     if( encode )
  585.     {   WriteRastData(False);
  586.         WriteRastInt(RLEFileSize);
  587.         WriteRastInt(RT_BYTE_ENCODED);
  588.     } else
  589.     {   size = (XRange%2)? XRange+1 : XRange;
  590.         WriteRastInt(size*YRange);
  591.         WriteRastInt(RT_STANDARD);
  592.     }
  593.  
  594.     cols = CompactColourMap();
  595.     WriteRastInt(RMT_EQUAL_RGB);
  596.     WriteRastInt(cols*3);
  597.  
  598.     for( i=0; i<cols; i++ ) fputc((int)RLut[Node[i]],OutFile);
  599.     for( i=0; i<cols; i++ ) fputc((int)GLut[Node[i]],OutFile);
  600.     for( i=0; i<cols; i++ ) fputc((int)BLut[Node[i]],OutFile);
  601. #else
  602.     WriteRastInt(24);
  603.  
  604.     if( encode )
  605.     {   WriteRastData(False);
  606.         WriteRastInt(RLEFileSize);
  607.         WriteRastInt(RT_BYTE_ENCODED);
  608.     } else
  609.     {   size = XRange*3;
  610.         if( size&1 ) size++;
  611.         WriteRastInt(size*YRange);
  612.         WriteRastInt(RT_STANDARD);
  613.     }
  614.     WriteRastInt(RMT_NONE);
  615.     WriteRastInt(0);
  616. #endif
  617.  
  618.     WriteRastData(True);
  619.     fclose( OutFile );
  620.     return( True );
  621. }
  622.  
  623.  
  624. static void OutputEPSFByte( val )
  625.     int val;
  626. {
  627.     register int i;
  628.  
  629.     i = val/16;  fputc( (i>9)? (i-10)+'A' : i+'0', OutFile );
  630.     i = val%16;  fputc( (i>9)? (i-10)+'A' : i+'0', OutFile );
  631.     if( (LineLength+=2) > 72 )
  632.     {   fputc('\n',OutFile);
  633.         LineLength = 0;
  634.     }
  635. }
  636.  
  637. static void EncodeEPSFPixel( val, col )
  638.     int val, col;
  639. {
  640.     register int r, g, b;
  641.     register int i;
  642.  
  643.     r = RComp(val);
  644.     g = GComp(val);
  645.     b = BComp(val);
  646.  
  647.     if( col )
  648.     {   OutputEPSFByte( r );
  649.         OutputEPSFByte( g );
  650.         OutputEPSFByte( b );
  651.     } else
  652.     {   i = (20*r + 32*g + 12*b)>>6;
  653.         OutputEPSFByte( i );
  654.     }
  655. }
  656.  
  657. int WriteEPSFFile( name, col, comp )
  658.     char *name;  int col, comp;
  659. {
  660.     register int xpos, ypos;
  661.     register int xsize, ysize;
  662.     register int rotpage;
  663.     register int x, y, i, j;
  664.  
  665.     register Pixel __huge *ptr;
  666.     int RLEBuffer[128];
  667.  
  668. #ifdef EIGHTBIT
  669.     for( i=0; i<256; i++ )
  670.         if( ULut[i] )
  671.             LutInv[Lut[i]] = i;
  672. #endif
  673.  
  674.     OutFile = fopen(name,"w");
  675.     if( !OutFile )
  676.     {   FatalOutputError(name);
  677.         return(False);
  678.     }
  679.  
  680.     if( XRange <= YRange )
  681.     {   rotpage = False; 
  682.         xsize = XRange; 
  683.         ysize = YRange;
  684.     } else
  685.     {   rotpage = True;  
  686.         xsize = YRange; 
  687.         ysize = XRange;
  688.     }
  689.  
  690.     if( xsize > (int)(BORDER*PAGEWIDE) )
  691.     {   ysize = (int)(ysize*(BORDER*PAGEWIDE)/xsize);
  692.         xsize = (int)(BORDER*PAGEWIDE);
  693.     }
  694.     if( ysize > (int)(BORDER*PAGEHIGH) )
  695.     {   xsize = (int)(xsize*(BORDER*PAGEHIGH)/ysize);
  696.         ysize = (int)(BORDER*PAGEHIGH);
  697.     }
  698.  
  699.     xpos = (int)(PAGEWIDE-xsize)/2;
  700.     ypos = (int)(PAGEHIGH-ysize)/2;
  701.  
  702.     fputs("%!PS-Adobe-2.0 EPSF-2.0\n",OutFile);
  703.     fputs("%%Creator: RasMol Version 2.3\n",OutFile);
  704.     fprintf(OutFile,"%%%%Title: %s\n",name);
  705.     fprintf(OutFile,"%%%%BoundingBox: %d %d ",xpos,ypos);
  706.     fprintf(OutFile,"%d %d\n",xpos+xsize,ypos+ysize);
  707.  
  708.     fputs("%%Pages: 1\n",OutFile);
  709.     fputs("%%EndComments\n",OutFile);
  710.     fputs("%%EndProlog\n",OutFile);
  711.     fputs("%%Page: 1 1\n",OutFile);
  712.  
  713.     fputs("gsave\n",OutFile);
  714.     fputs("10 dict begin\n",OutFile);
  715.     fprintf(OutFile,"%d %d translate\n",xpos,ypos);
  716.     fprintf(OutFile,"%d %d scale\n",xsize,ysize);
  717.     if( rotpage )
  718.     {   fputs("0.5 0.5 translate\n",OutFile);
  719.         fputs("90 rotate\n",OutFile);
  720.         fputs("-0.5 -0.5 translate\n",OutFile);
  721.     }
  722.     fputc('\n',OutFile);
  723.  
  724.     if( comp )
  725.     {   fputs("/rlecount 0 def\n",OutFile);
  726.         fputs("/rlebyte 1 string def\n",OutFile);
  727.         fprintf(OutFile,"/pixbuf %d string def\n", col?3:1 );
  728.         fputs("/reppixel { pixbuf } def\n",OutFile);
  729.         fputs("/getpixel { \n",OutFile);
  730.         fputs("  currentfile pixbuf readhexstring pop\n",OutFile);
  731.         fputs("} def\n\n",OutFile);
  732.  
  733.         if( col )
  734.         {   fputs("/colorimage where {\n",OutFile);
  735.             fputs("  pop\n",OutFile);
  736.             fputs("} {\n",OutFile);
  737.             fputs("  /bytebuf 1 string def\n",OutFile);
  738.             fputs("  /colorimage { pop pop image } def\n",OutFile);
  739.             fputs("  /reppixel { bytebuf } def\n",OutFile);
  740.             fputs("  /getpixel {\n",OutFile);
  741.             fputs("    currentfile pixbuf readhexstring pop pop\n",OutFile);
  742.             fputs("    bytebuf 0\n",OutFile);
  743.             fputs("    pixbuf 0 get 20 mul\n",OutFile);
  744.             fputs("    pixbuf 1 get 32 mul\n",OutFile);
  745.             fputs("    pixbuf 2 get 12 mul\n",OutFile);
  746.             fputs("    add add -6 bitshift put bytebuf\n",OutFile);
  747.             fputs("  } def\n",OutFile);
  748.             fputs("} ifelse\n\n",OutFile);
  749.         }
  750.  
  751.         fputs("/rledecode {\n",OutFile);
  752.         fputs("  rlecount 0 eq {\n",OutFile);
  753.         fputs("    currentfile rlebyte readhexstring pop\n",OutFile);
  754.         fprintf(OutFile,"    0 get dup %d gt {\n",EPSFCompRatio);
  755.         fprintf(OutFile,"      /rlecount exch %d sub def\n",EPSFCompRatio);
  756.         fputs("      /rleflag true def\n",OutFile);
  757.         fputs("    } {\n",OutFile);
  758.         fputs("      /rlecount exch def\n",OutFile);
  759.         fputs("      /rleflag false def\n",OutFile);
  760.         fputs("    } ifelse getpixel\n",OutFile);
  761.         fputs("  } {\n",OutFile);
  762.         fputs("    /rlecount rlecount 1 sub def\n",OutFile);
  763.         fputs("    rleflag { reppixel } { getpixel } ifelse\n",OutFile);
  764.         fputs("  } ifelse\n",OutFile);
  765.         fputs("} def\n",OutFile);
  766.     } else if( col )
  767.     {   fprintf(OutFile,"/scanbuf %d string def\n",XRange*3);
  768.         fputs("/colorimage where {\n",OutFile);
  769.         fputs("  pop\n",OutFile);
  770.         fputs("} {\n",OutFile);
  771.         fputs("  /pixbuf 3 string def\n",OutFile);
  772.         fputs("  /bytebuf 1 string def\n",OutFile);
  773.         fputs("  /colorimage {\n",OutFile);
  774.         fputs("    pop pop pop {\n",OutFile);
  775.         fputs("      currentfile pixbuf readhexstring pop pop\n",OutFile);
  776.         fputs("      bytebuf 0\n",OutFile);
  777.         fputs("      pixbuf 0 get 20 mul\n",OutFile);
  778.         fputs("      pixbuf 1 get 32 mul\n",OutFile);
  779.         fputs("      pixbuf 2 get 12 mul\n",OutFile);
  780.         fputs("      add add -6 bitshift put bytebuf\n",OutFile);
  781.         fputs("    } image\n",OutFile);
  782.         fputs("  } def\n",OutFile);
  783.         fputs("} ifelse\n\n",OutFile);
  784.     } else fprintf(OutFile,"/scanbuf %d string def\n\n",XRange);
  785.  
  786.     fprintf(OutFile,"%d %d %d\n",XRange,YRange,8);
  787.     fprintf(OutFile,"[%d 0 0 -%d 0 %d]\n",XRange,YRange,YRange);
  788.  
  789.     if( !comp )
  790.     {   fputs("{ currentfile scanbuf readhexstring pop }\n",OutFile);
  791.     } else fputs("{ rledecode }\n",OutFile);
  792.     if( col ) fputs("false 3 color",OutFile);
  793.     fputs("image\n",OutFile);
  794.  
  795. #ifdef IBMPC
  796.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  797. #endif
  798.  
  799. #ifndef INVERT
  800.     ptr = FBuffer; 
  801. #endif
  802.  
  803.     RLELength = 0;
  804.     LineLength = 0;
  805.     for( y=YRange-1; y>=0; y-- )
  806.     {
  807. #ifdef INVERT
  808.         ptr = FBuffer + (Long)y*XRange;
  809. #endif
  810.         for( x=0; x<XRange; x++ )
  811.         {   i = *ptr++;
  812.             if( comp )
  813.             {   if( RLELength )
  814.                 {   if( RLEEncode )
  815.                     {   if( (RLEPixel!=i) || (RLELength==256-EPSFCompRatio) )
  816.                         {   OutputEPSFByte(RLELength+EPSFCompRatio-1);
  817.                             EncodeEPSFPixel(RLEPixel,col);
  818.                             RLEEncode = False;
  819.                             RLEBuffer[0] = i;
  820.                             RLELength = 1;
  821.                         } else RLELength++;
  822.                     } else if( RLEBuffer[RLELength-1] == i )
  823.                     {   if( RLELength>1 )
  824.                         {   OutputEPSFByte(RLELength-2);
  825.                             for( j=0; j<RLELength-1; j++ )
  826.                                 EncodeEPSFPixel(RLEBuffer[j],col);
  827.                         }
  828.                         RLEEncode = True;
  829.                         RLELength = 2;
  830.                         RLEPixel = i;
  831.                     } else if( RLELength == EPSFCompRatio+1 )
  832.                     {   OutputEPSFByte(EPSFCompRatio);
  833.                         for( j=0; j<RLELength; j++ )
  834.                              EncodeEPSFPixel(RLEBuffer[j],col);
  835.                         RLEEncode = False;
  836.                         RLEBuffer[0] = i;
  837.                         RLELength = 1;
  838.                     } else RLEBuffer[RLELength++] = i;
  839.                 } else
  840.                 {   RLEEncode = False;
  841.                     RLEBuffer[0] = i;
  842.                     RLELength = 1;
  843.                 }
  844.             } else EncodeEPSFPixel( i, col );
  845.         }
  846.     }
  847.  
  848.     if( comp && RLELength )
  849.     {   if( RLEEncode )
  850.         {   OutputEPSFByte(RLELength+EPSFCompRatio-1);
  851.             EncodeEPSFPixel(RLEPixel,col);
  852.         } else
  853.         {   OutputEPSFByte(RLELength-1);
  854.             for( j=0; j<RLELength; j++ )
  855.                 EncodeEPSFPixel(RLEBuffer[j],col);
  856.         }
  857.     }
  858.  
  859.     if( LineLength ) 
  860.         fputc('\n',OutFile);
  861.     fputs("end\n",OutFile);
  862.     fputs("grestore\n",OutFile);
  863.     fputs("showpage\n",OutFile);
  864.     fputs("%%Trailer\n",OutFile);
  865.     fputs("%%EOF\n",OutFile);
  866.     fclose( OutFile );
  867. #ifdef IBMPC
  868.     GlobalUnlock(FBufHandle);
  869. #endif
  870.     return( True );
  871. }
  872.  
  873.  
  874.  
  875. /* Flush AbsMode buffer */
  876. static void FlushBMPBuffer()
  877. {
  878.     if( RLEOutput )
  879.     {   fputc(0x00,OutFile);
  880.         fputc(PacketLen,OutFile);
  881.         fwrite((char*)Buffer,1,PacketLen,OutFile);
  882.         if( PacketLen%2 ) fputc(0x00,OutFile);    
  883.     } else
  884.         RLEFileSize += (PacketLen%2)+PacketLen+2;
  885.      
  886.     PacketLen = 0;
  887. }
  888.  
  889. /* Flush RLEMode buffer */
  890. static void FlushBMPPackets()
  891. {
  892.     register int i;
  893.     
  894.     if( PacketLen )
  895.         FlushBMPBuffer();
  896.  
  897.     if( RLEOutput )
  898.     {   for( i=0; i<BMPCount; i++ )
  899.         {   fputc(BMPBuffer[i].len,OutFile);
  900.             fputc(BMPBuffer[i].ch,OutFile);
  901.         }
  902.     } else RLEFileSize += (BMPCount<<1);
  903.     BMPCount = BMPTotal = 0;
  904. }
  905.  
  906. static void ProcessBMPPacket()
  907. {
  908.     register int cost;
  909.     register int i,j;
  910.     
  911.     BMPBuffer[BMPCount].len = RLELength;
  912.     BMPBuffer[BMPCount].ch = RLEChar;
  913.     BMPTotal += RLELength;
  914.     RLELength = 0;
  915.     BMPCount++;    
  916.  
  917.  
  918.     /* RLEMode is more efficient */
  919.     if( BMPTotal > BMPCount+5 )
  920.     {   FlushBMPPackets();
  921.         return;
  922.     }
  923.     
  924.     /* Flush AbsMode buffer */
  925.     if( PacketLen+BMPTotal>255 )
  926.         FlushBMPBuffer();
  927.     
  928.  
  929.     /* Cannot leave RLEMode */
  930.     if( PacketLen+BMPTotal<3 )
  931.         return;
  932.         
  933.     /* Determine AbsMode cost */
  934.     if( PacketLen )
  935.     {   cost = BMPTotal - (PacketLen%2);
  936.         cost += (cost%2);
  937.     } else cost = (BMPTotal%2)+BMPTotal+2;    
  938.  
  939.     /* Put RLE Packets into AbsMode buffer */
  940.     if( cost <= (int)(BMPCount<<1) )
  941.     {   for( i=0; i<BMPCount; i++ )
  942.             for( j=0; j<(int)BMPBuffer[i].len; j++ )
  943.                 Buffer[PacketLen++] = BMPBuffer[i].ch;
  944.         BMPCount = BMPTotal = 0;
  945.     }
  946. }
  947.  
  948. /* Collect pixels into RLE Packets */
  949. static void WriteBMPCode( val )
  950.     int val;
  951. {
  952.     if( !RLELength )
  953.     {   RLELength = 1;
  954.         RLEChar = val;
  955.     } else
  956.         if( (RLEChar!=val) || (RLELength==255) )
  957.         {   ProcessBMPPacket();
  958.             RLELength = 1;
  959.             RLEChar = val;
  960.         } else
  961.             RLELength++;
  962. }
  963.  
  964. static void WriteBMPData( output )
  965.     int output;
  966. {
  967.     register Pixel __huge *ptr;
  968.     register int x,y;
  969.     
  970.     RLEOutput = output;
  971.     RLEFileSize = 0;   BMPCount = 0;
  972.     RLELength = 0;     BMPTotal = 0;
  973.     PacketLen = 0; 
  974.  
  975. #ifdef INVERT
  976.     ptr = FBuffer;
  977. #endif
  978.  
  979.     for( y=YRange-1; y>=0; y-- )
  980.     {
  981. #ifndef INVERT
  982.         ptr = FBuffer + (Long)y*XRange;
  983. #endif
  984.         for( x=0; x<XRange; x++ )
  985.             WriteBMPCode(*ptr++);
  986.  
  987.         for( x=0; x<BMPPad; x++ )
  988.             WriteBMPCode(0x00);
  989.  
  990.         /* Flush RLE codes */
  991.         ProcessBMPPacket();
  992.         FlushBMPPackets();
  993.         
  994.         if( RLEOutput )
  995.         {   /* End of line code */
  996.             fputc(0x00,OutFile);
  997.             fputc((y?0x00:0x01),OutFile);
  998.         } else RLEFileSize += 2;
  999.     }
  1000. }
  1001.  
  1002.  
  1003. #if defined(__STDC__) || defined(IBMPC)
  1004. static void WriteBMPWord( Card );
  1005. #endif
  1006.  
  1007. static void WriteBMPWord( val )
  1008.     Card val;
  1009. {
  1010.     fputc((int)(val&0xff),OutFile);
  1011.     fputc((int)((val>>8) &0xff),OutFile);
  1012.     fputc((int)((val>>16)&0xff),OutFile);
  1013.     fputc((int)((val>>24)&0xff),OutFile);
  1014. }
  1015.     
  1016. int WriteBMPFile( name )
  1017.     char *name;
  1018. {
  1019.     register Pixel __huge *ptr;
  1020.     register int x,y,i,raw;
  1021.     register Card size;
  1022.  
  1023. #ifdef EIGHTBIT
  1024. #ifdef IBMPC
  1025.     OutFile = fopen(name,"wb");
  1026. #else
  1027.     OutFile = fopen(name,"w");
  1028. #endif
  1029.     if( !OutFile )
  1030.     {    FatalOutputError(name);
  1031.          return( False );
  1032.     }
  1033.  
  1034. #ifdef IBMPC
  1035.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  1036. #endif
  1037.  
  1038.     /* zero-pad scanlines to long */
  1039.     if( (BMPPad=XRange%4) ) 
  1040.          BMPPad = 4-BMPPad; 
  1041.    
  1042.     WriteBMPData(False);
  1043.     size = (Long)(XRange+BMPPad)*YRange;
  1044.     if( RLEFileSize<size )
  1045.     {   size = RLEFileSize;
  1046.         raw = False;
  1047.     } else raw = True;
  1048.  
  1049.  
  1050.     fputc('B',OutFile); 
  1051.     fputc('M',OutFile);
  1052.     WriteBMPWord(size+1078);
  1053.     WriteBMPWord((Card)0);
  1054.     WriteBMPWord((Card)1078);
  1055.  
  1056.     WriteBMPWord((Card)40);
  1057.     WriteBMPWord((Card)XRange);
  1058.     WriteBMPWord((Card)YRange);
  1059.     fputc(0x01,OutFile);  fputc(0x00,OutFile);
  1060.     fputc(0x08,OutFile);  fputc(0x00,OutFile);
  1061.     WriteBMPWord(raw? (Card)0 : (Card)1);
  1062.     WriteBMPWord(size);
  1063.     
  1064.     WriteBMPWord((Card)0);
  1065.     WriteBMPWord((Card)0);
  1066.     WriteBMPWord((Card)256);
  1067.     WriteBMPWord((Card)256);
  1068.  
  1069.     for( i=0; i<256; i++ )
  1070.     {   fputc((int)BLut[i],OutFile);
  1071.         fputc((int)GLut[i],OutFile);
  1072.         fputc((int)RLut[i],OutFile);
  1073.         fputc(0x00,OutFile);
  1074.     }
  1075.  
  1076.     if( raw )
  1077.     {   
  1078. #ifdef INVERT
  1079.         ptr = FBuffer;
  1080. #endif
  1081.         for( y=YRange-1; y>=0; y-- )
  1082.         {
  1083. #ifndef INVERT
  1084.             ptr = FBuffer + (Long)y*XRange;
  1085. #endif
  1086.             for( x=0; x<XRange; x++ )
  1087.                 fputc((int)(*ptr++),OutFile);
  1088.             for( x=0; x<BMPPad; x++ )
  1089.                 fputc(0x00,OutFile);
  1090.             fputc(0x00,OutFile);
  1091.             fputc((y?0x00:0x01),OutFile);
  1092.         }
  1093.     } else
  1094.         WriteBMPData(True);
  1095.  
  1096. #ifdef IBMPC
  1097.     GlobalUnlock(FBufHandle);
  1098. #endif
  1099.     fclose(OutFile);
  1100.     return(True);
  1101. #else
  1102.     if( CommandActive ) WriteChar('\n');
  1103.     WriteString("Output Error: 24 bit BMP files unsupported!\n");
  1104.     CommandActive = False;
  1105.     return( False );
  1106. #endif
  1107. }
  1108.  
  1109.  
  1110. static void MolScriptSegment( ptr, src, dst, chain )
  1111.     char *ptr;  int src, dst;  char chain;
  1112. {   
  1113.     putchar(' ');
  1114.     if( (chain!=' ') && !isdigit(chain) ) 
  1115.     {   fprintf(OutFile,"%s from %c%d to %c%d;\n",ptr,chain,src,chain,dst);
  1116.     } else fprintf(OutFile,"%s from %d to %d\n",ptr,src,dst);
  1117.     fputs(";\n",OutFile);
  1118. }
  1119.  
  1120.  
  1121. int WriteMolScriptFile( name )
  1122.     char *name;
  1123. {
  1124.     register Real psi, phi, theta;
  1125.     register Chain __far *chain;
  1126.     register Group __far *group;
  1127.     register Group __far *next;
  1128.     register Group __far *prev;
  1129.     register int flag,len;
  1130.     register char *ptr;
  1131.  
  1132.     if( !Database )
  1133.         return(False);
  1134.  
  1135.     OutFile = fopen(name,"w");
  1136.     if( !OutFile )
  1137.     {   FatalOutputError(name);
  1138.         return(False);
  1139.     }
  1140.     fprintf(OutFile,"! File: %s\n",name);
  1141.     fputs("! Creator: RasMol Version 2.3\n",OutFile);
  1142.     fputs("! Version: MolScript v1.3\n\n",OutFile);
  1143.  
  1144.     fputs("plot\n",OutFile);
  1145.     if( BackR || BackG || BackB )
  1146.     {   fputs("  background rgb ",OutFile);
  1147.         fprintf(OutFile,"%#g ",  BackR/255.0);
  1148.         fprintf(OutFile,"%#g ",  BackG/255.0);
  1149.         fprintf(OutFile,"%#g;\n",BackB/255.0);
  1150.     }
  1151.     fputc('\n',OutFile);
  1152.  
  1153.     fprintf(OutFile,"  read mol \"%s\";\n",InfoFileName);
  1154.     fputs("  transform atom *\n",OutFile);
  1155.     fputs("    by centre position atom *\n",OutFile);
  1156.     fputs("    by rotation x 180.0",OutFile);
  1157.  
  1158.     phi = Rad2Deg*asin(RotX[2]);
  1159.     if( (int)phi == 90 )
  1160.     {   theta = -Rad2Deg*atan2(RotY[0],RotY[1]);
  1161.         psi = 0;
  1162.     } else if( (int)phi == -90 )
  1163.     {   theta = Rad2Deg*atan2(RotY[0],RotY[1]);
  1164.         psi = 0;
  1165.     } else /* General Case! */
  1166.     {   theta = Rad2Deg*atan2(RotY[2],RotZ[2]);
  1167.         psi =  -Rad2Deg*atan2(RotX[1],RotX[0]);
  1168.     }
  1169.  
  1170. #ifdef INVERT
  1171.     if( (int)psi )   fprintf(OutFile,"\n    by rotation z %#g",psi);
  1172.     if( (int)phi )   fprintf(OutFile,"\n    by rotation y %#g",phi);
  1173.     if( (int)theta ) fprintf(OutFile,"\n    by rotation x %#g",-theta);
  1174. #else
  1175.     if( (int)psi )   fprintf(OutFile,"\n    by rotation z %#g",-psi);
  1176.     if( (int)phi )   fprintf(OutFile,"\n    by rotation y %#g",phi);
  1177.     if( (int)theta ) fprintf(OutFile,"\n    by rotation x %#g",theta);
  1178. #endif
  1179.     fputs(";\n\n",OutFile);
  1180.  
  1181.     /* fputs("  trace amino-acids;\n",OutFile); */
  1182.  
  1183.     if( Database->clist )
  1184.     {   if( InfoHelixCount<0 )
  1185.             DetermineStructure();
  1186.  
  1187.         for( chain=Database->clist; chain; chain=chain->cnext )
  1188.         {   prev = chain->glist;
  1189.             for( group=prev; group && group->gnext; group=next )
  1190.             {   next = group->gnext;
  1191.                 flag = group->flag & next->flag;
  1192.  
  1193.                 if( flag&HelixFlag )
  1194.                 {   flag = HelixFlag;
  1195.                     ptr = "helix";
  1196.                 } else if( flag&SheetFlag )
  1197.                 {   flag = SheetFlag;
  1198.                     ptr = "strand";
  1199.                 } else if( flag&TurnFlag )
  1200.                 {   fputs("  turn residue ",OutFile);
  1201.                     if( chain->ident != ' ' )
  1202.                         fputc(chain->ident,OutFile);
  1203.                     fprintf(OutFile,"%d;\n",group->serno);
  1204.                     continue;
  1205.                 } else continue;
  1206.  
  1207.                 len = 2;  /* Determine Structure Length */
  1208.                 while( next->gnext && (next->gnext->flag&flag) )
  1209.                 {   next = next->gnext;
  1210.                     len++;
  1211.                 }
  1212.  
  1213.                 if( len>2 )
  1214.                 {   if( prev ) /* MolScript coil or turn? */
  1215.                        MolScriptSegment("coil",prev->serno,group->serno,
  1216.                                               chain->ident);
  1217.                     MolScriptSegment(ptr,group->serno,next->serno,
  1218.                                          chain->ident);
  1219.                 prev = next;
  1220.                 } 
  1221.             }
  1222.  
  1223.             if( prev != group )  /* C-terminal coil/turn */
  1224.                 MolScriptSegment("coil",prev->serno,group->serno,chain->ident);
  1225.         }
  1226.     }
  1227.  
  1228.     fputs("end_plot\n",OutFile);
  1229.     fclose(OutFile);
  1230.     return( True );
  1231. }
  1232.  
  1233.  
  1234.  
  1235. int WriteScriptFile( name )
  1236.     char *name;
  1237. {
  1238.     register int theta,phi,psi;
  1239.     register char *ptr;
  1240.     register int temp;
  1241.  
  1242.     OutFile = fopen(name,"w");
  1243.     if( !OutFile )
  1244.     {   FatalOutputError(name);
  1245.         return(False);
  1246.     }
  1247.  
  1248.     fprintf(OutFile,"# File: %s\n",name);
  1249.     fputs("# Creator: RasMol Version 2.3\n\n",OutFile);
  1250.     fprintf(OutFile,"background [%d,%d,%d]\n",BackR,BackG,BackB);
  1251.     if( !Database )
  1252.     {   /* No Molecule! */
  1253.         fclose(OutFile);
  1254.         return(True);
  1255.     }
  1256.  
  1257.     /* Colour Details */
  1258.     fprintf(OutFile,"set ambient %d\n", (int)(100*Ambient) );
  1259.     fputs("set specular ",OutFile);
  1260.     if( FakeSpecular )
  1261.     {   fprintf(OutFile,"on\nset specpower %d\n",SpecPower);
  1262.     } else fputs("off\n",OutFile);
  1263.     putc('\n',OutFile);
  1264.  
  1265.     /* Transformation */
  1266.     fputs("reset\n",OutFile);
  1267.     if( UseSlabPlane )
  1268.     {   if( (temp = (int)(50.0*DialValue[7])) )
  1269.         {   fprintf(OutFile,"slab %d\n",temp+50);
  1270.         } else fputs("slab on\n",OutFile);
  1271.  
  1272.         fputs("set slabmode ",OutFile);
  1273.         switch( SlabMode )
  1274.         {   default:            
  1275.             case(SlabClose):    ptr = "solid";    break;
  1276.             case(SlabReject):   ptr = "reject";   break;
  1277.             case(SlabHalf):     ptr = "half";     break;
  1278.             case(SlabHollow):   ptr = "hollow";   break;
  1279.             case(SlabSection):  ptr = "section";
  1280.         }
  1281.         fputs(ptr,OutFile);
  1282.         putc('\n',OutFile);
  1283.     } else fputs("slab off\n",OutFile);
  1284.  
  1285.     phi = Round(Rad2Deg*asin(RotX[2]));
  1286.     if( phi == 90 )
  1287.     {   theta = -Round(Rad2Deg*atan2(RotY[0],RotY[1]));
  1288.         psi = 0;
  1289.     } else if( phi == -90 )
  1290.     {   theta = Round(Rad2Deg*atan2(RotY[0],RotY[1]));
  1291.         psi = 0;
  1292.     } else /* General Case! */
  1293.     {   theta = Round(Rad2Deg*atan2(RotY[2],RotZ[2]));
  1294.         psi =  Round(-Rad2Deg*atan2(RotX[1],RotX[0]));
  1295.     }
  1296.  
  1297. #ifdef INVERT
  1298.     if( psi )   fprintf(OutFile,"rotate z %d\n",-psi);
  1299.     if( phi )   fprintf(OutFile,"rotate y %d\n",phi);
  1300.     if( theta ) fprintf(OutFile,"rotate x %d\n",-theta);
  1301. #else
  1302.     if( psi )   fprintf(OutFile,"rotate z %d\n",psi);
  1303.     if( phi )   fprintf(OutFile,"rotate y %d\n",phi);
  1304.     if( theta ) fprintf(OutFile,"rotate x %d\n",theta);
  1305. #endif
  1306.  
  1307.     if( (temp = (int)(100.0*DialValue[4])) )
  1308.         fprintf(OutFile,"translate x %d\n",temp);
  1309.     if( (temp = (int)(100.0*DialValue[5])) )
  1310. #ifdef INVERT
  1311.         fprintf(OutFile,"translate y %d\n",-temp);
  1312. #else
  1313.         fprintf(OutFile,"translate y %d\n",temp);
  1314. #endif
  1315.  
  1316.     if( DialValue[3] != 0.0 )
  1317.     {   if( DialValue[3]<0.0 )
  1318.         {   temp = (int)(100*DialValue[3]);
  1319.         } else temp = (int)(100*MaxZoom*DialValue[3]);
  1320.         fprintf(OutFile,"zoom %d\n",temp+100);
  1321.     }
  1322.     putc('\n',OutFile);
  1323.  
  1324.     /* Rendering */
  1325.     if( DrawAtoms )
  1326.     {   fprintf(OutFile,"set shadows %s\n", UseShadow? "on" : "off" );
  1327.     }
  1328.  
  1329.     if( UseSlabPlane && (SlabMode==SlabSection) )
  1330.     {   /* Section Mode Slabbing! */
  1331.         fclose(OutFile);
  1332.         return(True);
  1333.     }
  1334.  
  1335.     if( Database->slist )
  1336.     {   fputs("set ssbond ",OutFile);
  1337.         fputs(SSBondMode?"backbone":"sidechain",OutFile);
  1338.         fputs("\nssbonds on\n",OutFile);
  1339.     }
  1340.  
  1341.     if( Database->hlist )
  1342.     {   fputs("set hbond ",OutFile);
  1343.         fputs(HBondMode?"backbone":"sidechain",OutFile);
  1344.         fputs("\nhbonds on\n",OutFile);
  1345.     }
  1346.  
  1347.     if( DrawRibbon )
  1348.     {   if( !RibbonMode )
  1349.         {   fprintf(OutFile,"set strands %d\n",SplineCount);
  1350.             fputs("set ribbons strands\n",OutFile);
  1351.         } else fputs("set ribbons solid\n",OutFile);
  1352.         
  1353.     }
  1354.  
  1355.     fprintf(OutFile,"set axes %s\n", DrawAxes? "on":"off" );
  1356.     fprintf(OutFile,"set boundingbox %s\n", DrawBoundBox? "on":"off" );
  1357.     fprintf(OutFile,"set unitcell %s\n", DrawUnitCell? "on":"off" );
  1358.  
  1359.     fclose(OutFile);
  1360.     return( True );
  1361. }
  1362.  
  1363.  
  1364. #if defined(__STDC__) || defined(IBMPC)
  1365. static int FindDepth( PSItemPtr, int );
  1366. static void DepthSort( PSItemPtr __far*, char __far*, int );
  1367. #endif
  1368.  
  1369. static int FindDepth( item, type )
  1370.      PSItemPtr item;  int type;
  1371. {
  1372.     register Atom __far *atom;
  1373.     register Bond __far *bond;
  1374.     register int result;
  1375.  
  1376.     if( type==PSSphere )
  1377.     {   atom = (Atom __far*)item;
  1378.         result = atom->z;
  1379.     } else /* PSLine or PSStick */
  1380.     {   bond = (Bond __far*)item;
  1381.         result = bond->srcatom->z;
  1382.         if( result < bond->dstatom->z )
  1383.             result = bond->dstatom->z;
  1384.     }
  1385.     return( result );
  1386. }
  1387.  
  1388.  
  1389. static void DepthSort( data, type, count )
  1390.     PSItemPtr __far *data;
  1391.     char __far *type;
  1392.     int count;
  1393. {
  1394.     register char ttmp;
  1395.     register void __far *dtmp;
  1396.     register int i, j, k;
  1397.     register int depth;
  1398.     register int temp;
  1399.  
  1400.     for( i=1; i<count; i++ )
  1401.     {   dtmp = data[i];  
  1402.         ttmp = type[i];
  1403.  
  1404.         j = i-1;
  1405.         depth = FindDepth(dtmp,ttmp);
  1406.         temp = FindDepth(data[j],type[j]);
  1407.         while( (depth<temp) || ((depth==temp)&&(ttmp<type[j])) )
  1408.             if( j-- ) 
  1409.             {   temp = FindDepth(data[j],type[j]);
  1410.             } else break;
  1411.         j++;
  1412.  
  1413.         if( j != i )
  1414.         {   for( k=i; k>j; k-- )
  1415.             {    data[k] = data[k-1];
  1416.                  type[k] = type[k-1];
  1417.             }
  1418.             data[j] = dtmp;
  1419.             type[j] = ttmp;
  1420.         }
  1421.     }
  1422. }
  1423.  
  1424. #if defined(__STDC__) || defined(IBMPC)
  1425. static void WriteVectSphere( Atom __far* );
  1426. static void WriteVectStick( Bond __far* );
  1427. static void WriteVectWire( Bond __far* );
  1428. #endif
  1429.  
  1430.  
  1431. static void WriteVectColour( col )
  1432.     int col;
  1433. {
  1434.     if( col != VectCol )
  1435.     {   fprintf(OutFile,"%g ",RLut[col]/255.0);
  1436.         fprintf(OutFile,"%g ",GLut[col]/255.0);
  1437.         fprintf(OutFile,"%g ",BLut[col]/255.0);
  1438.         fputs("setrgbcolor\n",OutFile);
  1439.         VectCol = col;
  1440.     }
  1441. }
  1442.  
  1443.  
  1444. static void WriteVectSphere( ptr )
  1445.     Atom __far *ptr;
  1446. {
  1447.     register Real temp;
  1448.     register int i;
  1449.  
  1450.     temp = ptr->z/(2.0*ImageSize)+1.0;
  1451.     if( temp != LineWidth )
  1452.     {   fprintf(OutFile,"%g setlinewidth\n",temp);
  1453.         LineWidth = temp;
  1454.     }
  1455.  
  1456.     i = ptr->col + ColourMask;
  1457.     fprintf(OutFile,"%g ",RLut[i]/255.0);
  1458.     fprintf(OutFile,"%g ",GLut[i]/255.0);
  1459.     fprintf(OutFile,"%g ",BLut[i]/255.0);
  1460.     fprintf(OutFile,"%g ",Scale*ptr->radius);
  1461.  
  1462.     fprintf(OutFile,"%d %d ",ptr->x,ptr->y);
  1463.     fputs("Sphere\n",OutFile);
  1464. }
  1465.  
  1466. static void WriteVectWire( ptr )
  1467.     Bond __far *ptr;
  1468. {
  1469.     register Atom __far *src;
  1470.     register Atom __far *dst;
  1471.     register Real radius;
  1472.     register Real temp;
  1473.     register Real dist;
  1474.  
  1475.     register Real midx, midy;
  1476.     register Real endx, endy;
  1477.     register int col1, col2;
  1478.     register int dx, dy, dz;
  1479.     register Long dist2;
  1480.  
  1481.  
  1482.     src = ptr->srcatom;  
  1483.     dst = ptr->dstatom;
  1484.     if( src->z > dst->z )
  1485.     {   src = ptr->dstatom;
  1486.         dst = ptr->srcatom;
  1487.     }
  1488.  
  1489.     if( !ptr->col )
  1490.     {   col1 = src->col;
  1491.         col2 = dst->col;
  1492.     } else col1 = col2 = ptr->col;
  1493.  
  1494.     dx = dst->x - src->x;  
  1495.     dy = dst->y - src->y;
  1496.     dist2 = dx*dx + dy*dy;
  1497.     dist = sqrt( (double)dist2 );
  1498.  
  1499.     if( dst->flag & SphereFlag )
  1500.     {   radius = dst->radius*Scale;
  1501.         if( dist <= radius ) return;
  1502.  
  1503.         /* Test for second half obscured! */
  1504.         if( (col1!=col2) && (0.5*dist < radius) )
  1505.             col2 = col1;
  1506.     }
  1507.  
  1508.     if( src->flag & SphereFlag )
  1509.     {   radius = src->radius*Scale;
  1510.         if( dist <= radius ) return;
  1511.  
  1512.         /* Test for first half obscured! */
  1513.         if( (col1!=col2) && (0.5*dist < radius) )
  1514.             col1 = col2;
  1515.     }
  1516.  
  1517.  
  1518.     WriteVectColour( col1+ColourMask );
  1519.     temp = (src->z+dst->z)/(2.0*ImageSize)+1.0;
  1520.     if( temp != LineWidth )
  1521.     {   fprintf(OutFile,"%g setlinewidth\n",temp);
  1522.         LineWidth = temp;
  1523.     }
  1524.  
  1525.  
  1526.     if( src->flag & SphereFlag )
  1527.     {   dz = dst->z - src->z;
  1528.         dist = sqrt( (double)(dist2 + dz*dz) );
  1529.         endx = src->x + (radius*dx)/dist;
  1530.         endy = src->y + (radius*dy)/dist;
  1531.         fprintf(OutFile,"%g %g ",endx,endy);
  1532.     } else
  1533.         fprintf(OutFile,"%d %d ",src->x,src->y);
  1534.  
  1535.     if( col1 != col2 )
  1536.     {   midx = 0.5*(src->x + dst->x);
  1537.         midy = 0.5*(src->y + dst->y);
  1538.         fprintf(OutFile,"%g %g Wire\n",midx,midy);
  1539.  
  1540.         WriteVectColour( col2+ColourMask );
  1541.         fprintf(OutFile,"%g %g ",midx,midy);
  1542.     } 
  1543.     fprintf(OutFile,"%d %d Wire\n",dst->x,dst->y);
  1544. }
  1545.  
  1546.  
  1547. static void WriteVectStick( ptr )
  1548.     Bond __far *ptr;
  1549. {
  1550.     register Atom __far *src;
  1551.     register Atom __far *dst;
  1552.     register Real midx, midy;
  1553.     register Real relx, rely;
  1554.     register Real endx, endy;
  1555.     register Real radius, angle;
  1556.     register Real ratio, dist;
  1557.     register Real temp;
  1558.  
  1559.     register Long dist2;
  1560.     register int dx, dy, dz;
  1561.     register int col1, col2;
  1562.     register int i;
  1563.  
  1564.     if( !ptr->radius )
  1565.     {   WriteVectWire(ptr);
  1566.         return;
  1567.     }
  1568.  
  1569.     src = ptr->srcatom;  
  1570.     dst = ptr->dstatom;
  1571.     if( src->z > dst->z )
  1572.     {   src = ptr->dstatom;
  1573.         dst = ptr->srcatom;
  1574.     }
  1575.  
  1576.     if( !ptr->col )
  1577.     {   col1 = src->col;
  1578.         col2 = dst->col;
  1579.     } else col1 = col2 = ptr->col;
  1580.  
  1581.     dx = dst->x - src->x;  
  1582.     dy = dst->y - src->y;
  1583.     dist2 = dx*dx + dy*dy;
  1584.     dist = sqrt( (double)dist2 );
  1585.  
  1586.     if( dst->flag & SphereFlag )
  1587.     {   radius = dst->radius*Scale;
  1588.         if( dist <= radius ) return;
  1589.  
  1590.         /* Test for nearest half obscured! */
  1591.         if( (col1!=col2) && (0.5*dist < radius) )
  1592.             col2 = col1;
  1593.     }
  1594.  
  1595.     if( src->flag & SphereFlag )
  1596.     {   radius = src->radius*Scale;
  1597.         if( dist <= radius ) return;
  1598.  
  1599.         /* Test for furthest half obscured! */
  1600.         if( (col1!=col2) && (0.5*dist < radius) )
  1601.             col1 = col2;
  1602.     }
  1603.  
  1604.     temp = (src->z+dst->z)/(2.0*ImageSize)+1.0;
  1605.     if( temp != LineWidth )
  1606.     {   fprintf(OutFile,"%g setlinewidth\n",temp);
  1607.         LineWidth = temp;
  1608.     }
  1609.  
  1610.     radius = ptr->radius*Scale;
  1611.     angle = Rad2Deg*atan2((double)dy,(double)dx);
  1612.  
  1613.     if( col1 != col2 )
  1614.     {   midx = 0.5*(src->x + dst->x);
  1615.         midy = 0.5*(src->y + dst->y);
  1616.         relx = (radius*dx)/dist;
  1617.         rely = (radius*dy)/dist;
  1618.  
  1619.         fprintf(OutFile,"%g %g moveto\n",midx+rely,midy-relx);
  1620.         fprintf(OutFile,"%g %g lineto\n",midx-rely,midy+relx);
  1621.  
  1622.         dz = dst->z - src->z;
  1623.         dist = sqrt( (double)(dist2 + dz*dz) );
  1624.         ratio = dz/dist;
  1625.  
  1626.         if( (src->flag&SphereFlag) && (src->radius>ptr->radius) )
  1627.         {   temp = (Scale*src->radius)/dist;
  1628.             endx = src->x + temp*dx;
  1629.             endy = src->y + temp*dy;
  1630.  
  1631.             fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1632.             fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
  1633.         } else
  1634.         {   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
  1635.             fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
  1636.         }
  1637.         fputs("closepath ",OutFile);
  1638.  
  1639.         i = col1 + ColourMask;
  1640.         fprintf(OutFile,"%g ",RLut[i]/255.0);
  1641.         fprintf(OutFile,"%g ",GLut[i]/255.0);
  1642.         fprintf(OutFile,"%g ",BLut[i]/255.0);
  1643.         fputs("setrgbcolor fill\n",OutFile);
  1644.  
  1645.         fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
  1646.         fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);
  1647.         fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1648.         fprintf(OutFile,"%g %g StickEnd\n",midx,midy);
  1649.         fputs("closepath ",OutFile);
  1650.  
  1651.         i = col2 + ColourMask;
  1652.         fprintf(OutFile,"%g ",RLut[i]/255.0);
  1653.         fprintf(OutFile,"%g ",GLut[i]/255.0);
  1654.         fprintf(OutFile,"%g ",BLut[i]/255.0);
  1655.         fputs("setrgbcolor fill\n",OutFile);
  1656.  
  1657.         fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
  1658.         fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);
  1659.         if( (src->flag&SphereFlag) && (src->radius>ptr->radius) )
  1660.         {   fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1661.             fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
  1662.         } else
  1663.         {   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
  1664.             fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
  1665.         }
  1666.         fputs("closepath 0 setgray stroke\n",OutFile);
  1667.  
  1668.     } else /* col1 == col2! */
  1669.     {   fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
  1670.         fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);
  1671.  
  1672.         if( (src->flag&SphereFlag) && (src->radius>ptr->radius) )
  1673.         {   dz = dst->z - src->z;
  1674.             dist = sqrt( (double)(dist2 + dz*dz) );
  1675.             temp = (Scale*src->radius)/dist;
  1676.             endx = src->x + temp*dx;
  1677.             endy = src->y + temp*dy;
  1678.             ratio = dz/dist;
  1679.  
  1680.             fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1681.             fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
  1682.         } else
  1683.         {   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
  1684.             fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
  1685.         }
  1686.  
  1687.         i = col1 + ColourMask;
  1688.         fprintf(OutFile,"%g ",RLut[i]/255.0);
  1689.         fprintf(OutFile,"%g ",GLut[i]/255.0);
  1690.         fprintf(OutFile,"%g ",BLut[i]/255.0);
  1691.         fputs("Stick\n",OutFile);
  1692.     }
  1693.     VectCol = 0;
  1694. }
  1695.  
  1696.  
  1697. int WriteVectPSFile( name )
  1698.     char *name;
  1699. {
  1700.     register Real ambi;
  1701.     register Real temp, inten;
  1702.     register int xsize, ysize;
  1703.     register int xpos, ypos;
  1704.     register Long count;
  1705.     register int i;
  1706.  
  1707.     PSItemPtr __far *data;
  1708.     char __far *type;
  1709.  
  1710.     register Chain __far *chain;
  1711.     register Group __far *group;
  1712.     register Bond __far *bptr;
  1713.     register Atom __far *aptr;
  1714.  
  1715.  
  1716.     /* Determine the number of objects to draw! */
  1717.     count = 0;
  1718.     ForEachAtom if( aptr->flag&SphereFlag ) count++;
  1719.     ForEachBond if( bptr->flag&DrawBondFlag ) count++;
  1720.     ForEachBack if( bptr->flag&DrawBondFlag ) count++;
  1721.  
  1722.     if( !count ) 
  1723.         return( True );
  1724.  
  1725. #ifdef IBMPC
  1726.     if( count > 16383 )
  1727.     {   if( CommandActive ) WriteChar('\n');
  1728.         WriteString("Output Error: Too many PostScript objects!\n");
  1729.         CommandActive = False;
  1730.         return( False );
  1731.     }
  1732. #endif
  1733.  
  1734.     /* Allocate arrays for objects! */
  1735.     data = (PSItemPtr __far*)_fmalloc((size_t)count*sizeof(PSItemPtr));
  1736.     type = (char __far*)_fmalloc((size_t)count*sizeof(char));
  1737.     if( !data || !type )
  1738.     {   if( CommandActive ) WriteChar('\n');
  1739.         WriteString("Output Error: Not enough memory to create PostScript!\n");
  1740.         CommandActive = False;
  1741.  
  1742.         if( data ) _ffree( data );
  1743.         if( type ) _ffree( type );
  1744.         return( False );
  1745.     }
  1746.  
  1747.     OutFile = fopen(name,"w");
  1748.     if( !OutFile )
  1749.     {   FatalOutputError(name);
  1750.         return(False);
  1751.     }
  1752.  
  1753.     /* Determine the size of the image */
  1754.     ysize = (int)(YRange*(BORDER*PAGEWIDE)/XRange);
  1755.     if( ysize > (int)(BORDER*PAGEHIGH) )
  1756.     {   xsize = (int)(XRange*(BORDER*PAGEHIGH)/YRange);
  1757.         ysize = (int)(BORDER*PAGEHIGH);
  1758.     } else xsize = (int)(BORDER*PAGEWIDE);
  1759.  
  1760.     xpos = (int)(PAGEWIDE-xsize)/2;
  1761.     ypos = (int)(PAGEHIGH-ysize)/2;
  1762.  
  1763.     fputs("%!PS-Adobe-2.0 EPSF-2.0\n",OutFile);
  1764.     fputs("%%Creator: RasMol Version 2.3\n",OutFile);
  1765.     fprintf(OutFile,"%%%%Title: %s\n",name);
  1766.     fprintf(OutFile,"%%%%BoundingBox: %d %d ",xpos,ypos);
  1767.     fprintf(OutFile,"%d %d\n",xpos+xsize,ypos+ysize);
  1768.  
  1769.     fputs("%%Pages: 1\n",OutFile);
  1770.     fputs("%%EndComments\n",OutFile);
  1771.     fputs("%%EndProlog\n",OutFile);
  1772.     fputs("%%BeginSetup\n",OutFile);
  1773.  
  1774.     fputs("1 setlinecap 1 setlinejoin [] 0 setdash\n",OutFile);
  1775.     fputs("1 setlinewidth 0 setgray\n",OutFile);
  1776.     fputs("%%EndSetup\n",OutFile);
  1777.     fputs("%%Page: 1 1\n",OutFile);
  1778.  
  1779.     fputs("gsave\n",OutFile);
  1780.     fputs("5 dict begin\n\n",OutFile);
  1781.     fputs("/Inten {\n  dup 4 index mul exch\n",OutFile);
  1782.     fputs("  dup 4 index mul exch\n",OutFile);
  1783.     fputs("  3 index mul setrgbcolor\n} def\n\n",OutFile);
  1784.  
  1785.     fputs("/Wire {\n  moveto lineto stroke\n} def\n\n",OutFile);
  1786.  
  1787.     fputs("/Stick {\n  closepath gsave setrgbcolor fill\n",OutFile);
  1788.     fputs("  grestore 0 setgray stroke\n} def\n\n",OutFile);
  1789.     fputs("/StickEnd {\n  matrix currentmatrix 6 1 roll\n",OutFile);
  1790.     fputs("  translate rotate 1 scale\n",OutFile);
  1791.     fputs("  0 0 3 2 roll 90 -90 arc\n  setmatrix\n} def\n\n",OutFile);
  1792.  
  1793.     ambi = 0.5*Ambient;
  1794.     fputs("/Sphere {\n  gsave translate",OutFile);
  1795.     fputs(" 0 0 2 index 0 360 arc gsave\n",OutFile);
  1796.     fputs("  45 rotate dup -0.81649658092 mul scale\n",OutFile);
  1797.     fprintf(OutFile,"  gsave %g Inten fill grestore clip\n",ambi);
  1798.     inten = (1.0-ambi)/31;
  1799.     for( i=0; i<31; i++ )
  1800.     {   temp = (Real)(i+1)/32;
  1801.         fprintf(OutFile,"  newpath 0 %g ",(Real)i/32);
  1802.         fprintf(OutFile,"%g 0 360 arc ",sqrt(1.0-temp*temp));
  1803.         fprintf(OutFile,"%g Inten fill\n",i*inten+ambi);
  1804.     }
  1805.     fputs("  grestore 0 setgray stroke\n",OutFile);
  1806.     fputs("  pop pop pop grestore\n} def\n\n",OutFile);
  1807.  
  1808.     fprintf(OutFile,"%d %d translate\n",xpos,ypos+ysize);
  1809.     fprintf(OutFile,"%g ",(Real)xsize/XRange);
  1810.     fprintf(OutFile,"%g ",(Real)-ysize/YRange);
  1811.     fputs("scale\n\n",OutFile);
  1812.  
  1813.     fputs("newpath 0 0 moveto 0 ",OutFile);
  1814.     fprintf(OutFile,"%d rlineto %d 0 rlineto 0 %d",YRange,XRange,-YRange);
  1815.     fputs(" rlineto closepath\ngsave ",OutFile);
  1816.     if( BackR || BackG || BackB )
  1817.     {   fprintf(OutFile,"%g %g %g",BackR/255.0,BackG/255.0,BackB/255.0);
  1818.         fputs(" setrgbcolor fill grestore\ngsave ",OutFile);
  1819.     }
  1820.     fputs("clip newpath\n\n",OutFile);
  1821.  
  1822.     LineWidth = 1.0;
  1823.     VectSolid = True;
  1824.     VectCol = 0;
  1825.  
  1826.     i = 0;
  1827.     ForEachAtom
  1828.         if( aptr->flag&SphereFlag )
  1829.         {   type[i] = PSSphere; data[i] = aptr; i++;
  1830.         }
  1831.  
  1832.     ForEachBond
  1833.        if( bptr->flag&CylinderFlag )
  1834.        {   type[i] = PSStick; data[i] = bptr; i++;
  1835.        } else if( bptr->flag&WireFlag )
  1836.        {   type[i] = PSLine;  data[i] = bptr; i++;
  1837.        }
  1838.  
  1839.     ForEachBack
  1840.        if( bptr->flag&CylinderFlag )
  1841.        {   type[i] = PSStick; data[i] = bptr; i++;
  1842.        } else if( bptr->flag&WireFlag )
  1843.        {   type[i] = PSLine;  data[i] = bptr; i++;
  1844.        }
  1845.  
  1846.     if( count>1 )
  1847.         DepthSort(data,type,(int)count);
  1848.  
  1849.     for( i=0; i<count; i++ )
  1850.         if( type[i]==PSSphere )
  1851.         {   WriteVectSphere( data[i] );
  1852.         } else if( type[i]==PSStick )
  1853.         {   WriteVectStick( data[i] );
  1854.         } else /* PSWire */
  1855.             WriteVectWire( data[i] );
  1856.  
  1857.      
  1858.  
  1859.     fputs("grestore stroke end grestore\n",OutFile);
  1860.     fputs("showpage\n",OutFile);
  1861.     fputs("%%Trailer\n",OutFile);
  1862.     fputs("%%EOF\n",OutFile);
  1863.  
  1864.     fclose( OutFile );
  1865.     _ffree( data );
  1866.     _ffree( type );
  1867.     return(True);
  1868. }
  1869.  
  1870.  
  1871. void InitialiseOutFile()
  1872. {
  1873. #ifdef IBMPC
  1874.     /* Allocate Tables on FAR Heap */
  1875.     ABranch = (short __far*)_fmalloc(4096*sizeof(short));
  1876.     DBranch = (short __far*)_fmalloc(4096*sizeof(short));
  1877.     Hash = (short __far*)_fmalloc(256*sizeof(short));
  1878.     Node = (Byte __far*)_fmalloc(4096*sizeof(Byte));
  1879. #endif
  1880. }
  1881.  
  1882.